﻿using Abp.Domain.Repositories;
using Abp.EntityFrameworkCore.EFPlus;
using Abp.Json;
using Abp.Runtime.Session;
using Abp.Timing;
using Abp.UI;
using Mt.Site.Application.ContentManagement.Preview.Dto;
using Mt.Site.Core.Cache.Entities;
using System;
using System.Threading.Tasks;

namespace Mt.Site.Core.ContentManagement.Preview
{
    public class PreviewDataManager : MtSiteDomainServiceBase, IPreviewDataManager
    {
        public IAbpSession AbpSession { get; set; }

        private readonly IRepository<CacheBackUp, Guid> _cacheBackUpRepository;


        public PreviewDataManager(
            IRepository<CacheBackUp, Guid> cacheBackUpRepository)
        {
            _cacheBackUpRepository = cacheBackUpRepository;

            AbpSession = NullAbpSession.Instance;
        }

        public async Task<PreviewData> GetPreviewCacheDataAsync(string token)
        {
            Guid guid = Guid.Empty;
            Guid.TryParse(token, out guid);

            if (guid != Guid.Empty)
            {
                var now = Clock.Now;
                var backupData = await _cacheBackUpRepository.FirstOrDefaultAsync(c => c.Id == guid);

                if (backupData != null && Clock.Normalize(backupData.CacheExpireTime) > now)
                {
                    await _cacheBackUpRepository.BatchDeleteAsync(c => c.CacheExpireTime < now);
                    return new PreviewData
                    {

                        CacheItem = backupData.Data.FromJsonString<PreviewDataCacheItem>(),
                        CacheExpireTime = backupData.CacheExpireTime
                    };
                }
            }

            throw new UserFriendlyException(L("PreviewCacheTokenErrorMessage"));
        }

        /*
需求：

        1. 弹窗打开预览信息页（生成二维码，复制，延长有效期，访问）
        2. 不能再自动延长有效期，一旦过期也不该再有重启（那么就继续每个用户生成自己的链接，不共享，各自控制自己的分享有效期）
         
         */


        // get预览链接（现有的或生成新的）
        public async Task<PreviewTokenInfo> GetPreviewTokenAsync(PreviewTokenInput input)
        {
            if (!AbpSession.TenantId.HasValue)
            {
                throw new UserFriendlyException("不支持在host层面执行该操作");
            }

            var now = Clock.Now;
            await _cacheBackUpRepository.BatchDeleteAsync(c => c.CacheExpireTime < now);

            var dataId = GetDataKey(input);

            var cacheData = await _cacheBackUpRepository.FirstOrDefaultAsync(t => t.DataId == dataId);

            if (cacheData != null)
            {
                return new PreviewTokenInfo
                {
                    Token = cacheData.Id.ToString(),
                    CacheExpireTime = cacheData.CacheExpireTime
                };
            }

            //Create a cache item
            var cacheItem = new PreviewDataCacheItem
            {
                TenantId = AbpSession.TenantId,
                UserId = AbpSession.UserId,
                CultureName = AbpSession.CultureName(),
                MenuId = input.MenuId,
                Id = input.Id,
                Key = input.Key,
                AuxId = input.AuxId
            };

            var entity = new CacheBackUp
            {
                Id = Guid.NewGuid(),
                CacheExpireTime = now.AddDays(1),
                CreationTime = now,
                DataType = PreviewDataCacheItem.CacheName,
                Data = cacheItem.ToJsonString(),
                DataId = dataId
            };

            //Create a random token and save to the cache
            var token = await _cacheBackUpRepository.InsertAndGetIdAsync(entity);

            return new PreviewTokenInfo
            {
                Token = token.ToString(),
                CacheExpireTime = entity.CacheExpireTime
            };
        }

        // 延长期限
        public async Task<PreviewTokenInfo> UpdateTokenExpireTimeAsync(SetPreviewExpireTimeInput input)
        {
            if (!AbpSession.TenantId.HasValue)
            {
                throw new UserFriendlyException("不支持在host层面执行该操作");
            }

            var now = Clock.Now;
            await _cacheBackUpRepository.BatchDeleteAsync(c => c.CacheExpireTime < now);

            var cacheData = await _cacheBackUpRepository.FirstOrDefaultAsync(c => c.Id == input.Token);
            if (cacheData != null)
            {
                cacheData.CacheExpireTime = input.NewExpireTime;
                return new PreviewTokenInfo
                {
                    Token = cacheData.Id.ToString(),
                    CacheExpireTime = cacheData.CacheExpireTime
                };
            }

            throw new UserFriendlyException("当前分享链接已过期，请刷新重置");
        }

        private string GetDataKey(PreviewTokenInput input)
        {
            return $"{input.Id}@{input.MenuId}@{AbpSession.UserId}@{AbpSession.TenantId}";
        }
    }
}
